/*******************************************************************************
 * Copyright (c) 2025-08-06 @author <a href="mailto:iffiff1@gmail.com">Tyler Chen</a>.
 * All rights reserved.
 *
 * Contributors:
 *     <a href="mailto:iffiff1@gmail.com">Tyler Chen</a> - initial API and implementation.
 ******************************************************************************/
package org.iff.util.llm.qwen;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.iff.util.HttpClientUtil;
import org.iff.util.JSONUtil;
import org.iff.util.Utils;

import java.util.List;

/**
 * Qwen Chat 非流式结果数据结构
 * <pre>
 * {
 *     "choices": [
 *         {
 *             "message": {
 *                 "role": "assistant",
 *                 "content": "我是阿里云开发的一款超大规模语言模型，我叫通义千问。"
 *             },
 *             "finish_reason": "stop",
 *             "index": 0,
 *             "logprobs": null
 *         }
 *     ],
 *     "object": "chat.completion",
 *     "usage": {
 *         "prompt_tokens": 3019,
 *         "completion_tokens": 104,
 *         "total_tokens": 3123,
 *         "prompt_tokens_details": {
 *             "cached_tokens": 2048
 *         }
 *     },
 *     "created": 1735120033,
 *     "system_fingerprint": null,
 *     "model": "qwen-plus",
 *     "id": "chatcmpl-6ada9ed2-7f33-9de2-8bb0-78bd4035025a"
 * }
 * </pre>
 *
 * @author <a href="mailto:iffiff1@gmail.com">Tyler Chen</a>
 * @since 2025-08-06
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class TextChat {
    @JsonProperty("choices")
    private List<Choices> choices;
    @JsonProperty("object")
    private String object;
    @JsonProperty("usage")
    private Usage usage;
    @JsonProperty("created")
    private Long created;
    @JsonProperty("system_fingerprint")
    private Object systemFingerprint;
    @JsonProperty("model")
    private String model;
    @JsonProperty("id")
    private String id;

    public static void main(String[] args) throws Exception {
        String sys = "你是航空行业助手，请用中文回答问题";
        String msg = "下面<notam>标签的内容是航行通告，要求如下：\n" +
                "1.把通告中转为中文通告结果放到<result>标签，如果是中文通告则不需要转换，原文输出到<result>标签即可；\n" +
                "2.把原通告按下面规则再转换一次，需要保留报文格式通告的每一项都要输出，只需要把符合下面规则的数据按规则来替换原内容，结果放到<format>标签中；\n" +
                "3.时间格式转换为：[Date::Daily|Workday|Weekend::YYYY-MM-DD HH:mm:ss UTC+?]，如果只有时间没有日期的情况格式转换为为：[Time::Daily|Workday|Weekend::HH:mm:ss]；\n" +
                "4.经纬度格式转换为：[经度::经度数据]，[纬度::纬度数据]；\n" +
                "5.跑道 RWY 格式转换为：[RWY::跑道名称]；\n" +
                "6.滑行道 TWY，TXL 格式转换为：[TWY::滑行道名称]；\n" +
                "7.AIP或AIRAC补充资料格式转换为：[AIPSUP::资料编号]；\n" +
                "8.高度格式转换为：[Height::高度含单位]；\n" +
                "9.宽度格式转换为：[Width::宽度度含单位]；\n" +
                "10.速度格式转换为：[Speed::速度度含单位]；\n" +
                "11.重量格式转换为：[Weight::重量度含单位]；\n" +
                "12.情报区四字码格式转换为：[Area::情报区代码::情报区中文名称]；\n" +
                "13.机场四字码格式转换为：[AirPort::机场代码::机场中文名称]；\n" +
                "14.最后添加通告的原因，格式为：[Reason::原因]；\n" +
                "<notam>\n" +
                "U3974/24 NOTAMN\n" +
                "Q) RJJJ/QWULW\n" +
                "A) RJJJ\n" +
                "B) 2025-02-01 05:48:59\n" +
                "C) 2025-02-19 16:52:59\n" +
                "D) 2134/0838\n" +
                "E) UNMANNED ACFT(FIXED WING):\n" +
                "1.FLT AREA: BOUNDED BY FLW POINTS\n" +
                "            345530N1370701E 345532N1370657E\n" +
                "            345521N1370646E 345519N1370650E\n" +
                "            (ANJO-SHI,OKAZAKI-SHI IN AICHI)\n" +
                "2.WT      : 15KG\n" +
                "3.FLT TIME: HJ\n" +
                "4.RMK     : THIS NOTAM WILL BE INCORPORATED IN SUP\n" +
                "F) SFC\n" +
                "G) 1379FT AMSL\n" +
                "</notam>";

        String json = JSONUtil.toJsonString(TextMessage.of()
                        .stream(false)
                        .model("qwen-plus")
                        .message(TextMessage.ROLE_SYSTEM, sys)
                        .message(TextMessage.ROLE_USER, msg),
                true);
        String post = HttpClientUtil.post("https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions", json,
                HttpClientUtil.HttpOptions.create().authorization("Bearer " + System.getenv("API_KEY_ALIYUN"))
        );
        System.out.println(post);
        TextChat qwenChat = JSONUtil.fromJson(post, TextChat.class);
        System.out.println(JSONUtil.toJsonString(qwenChat, true));
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class Choices {
        @JsonProperty("message")
        private Message message;
        @JsonProperty("finish_reason")
        private String finishReason;
        @JsonProperty("index")
        private Integer index;
        @JsonProperty("logprobs")
        private Object logprobs;
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class Message {
        @JsonProperty("role")
        private String role;
        @JsonProperty("content")
        private String content;
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class Usage {
        @JsonProperty("prompt_tokens")
        private Integer promptTokens;
        @JsonProperty("completion_tokens")
        private Integer completionTokens;
        @JsonProperty("total_tokens")
        private Integer totalTokens;
        @JsonProperty("prompt_tokens_details")
        private PromptTokensDetails promptTokensDetails;
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class PromptTokensDetails {
        @JsonProperty("cached_tokens")
        private Integer cachedTokens;
    }
}

